Skip to content

Keep Activity from waking a runtime-suspended NVIDIA GPU - #11675

Open
anant1811 wants to merge 1 commit into
omacom:quattrofrom
anant1811:fix/btop-nvidia-runtime-suspend
Open

anant1811 wants to merge 1 commit into
omacom:quattrofrom
anant1811:fix/btop-nvidia-runtime-suspend

Conversation

@anant1811

Copy link
Copy Markdown

btop initialises NVML at startup whenever shown_gpus lists nvidia, whether or not a GPU box is on screen. On a hybrid laptop whose iGPU drives every output, opening Activity therefore resumed the discrete GPU and held it awake for as long as btop ran, on battery included.

Route the Activity binding through omarchy-launch-activity, which drops nvidia from shown_gpus while every NVIDIA GPU is runtime-suspended and puts it back once the card is awake. The check (omarchy-hw-nvidia-suspended) reads the cached sysfs power/runtime_status, which unlike lspci or NVML does not itself wake the card — the same criterion the report measured against.

Fixes #11184

Testing

New hw-nvidia-suspended-test.sh (5 cases) and launch-activity-test.sh (4 cases). Also exercised the launcher end-to-end with the real detector and the shipped btop.conf: no NVIDIA → file untouched; simulated suspended NVIDIA → only shown_gpus changes; awake again → file restored exactly. Full test/shell run shows only the pre-existing environmental failures.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LKJ7WaM8LCBtL91KJe3wQT

btop initialises NVML at startup whenever shown_gpus lists nvidia,
whether or not a GPU box is on screen. On a hybrid laptop whose iGPU
drives every output, opening Activity therefore resumed the discrete
GPU and held it awake for as long as btop ran, on battery included.

Route the Activity binding through omarchy-launch-activity, which
drops nvidia from shown_gpus while every NVIDIA GPU is runtime
suspended and puts it back once the card is awake. The check reads the
cached sysfs power state, which unlike lspci or NVML does not itself
wake the card.

Fixes omacom#11184

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LKJ7WaM8LCBtL91KJe3wQT
@llstrk

llstrk commented Oct 1, 2026

Copy link
Copy Markdown

Automated AI review

Community review: Independent automated community review, unaffiliated with the Omarchy team, intended to help prepare PRs for their review.

Outcome: omarchy-launch-activity adds nvidia to shown_gpus lists that never had it, which can keep the dGPU awake for users who had removed it.

Launcher re-adds nvidia it did not remove

bin/omarchy-launch-activity prepends nvidia whenever omarchy-hw-nvidia-suspended exits non-zero, including when the card is awake or there is no NVIDIA GPU. A user list such as amd intel (the value #11184 suggests) becomes nvidia amd intel, so btop initialises NVML and keeps an awake card from suspending while Activity is open. A list of only nvidia becomes "" while the card sleeps and is never restored, because the [[ -n $shown ]] guard then skips the file.

Suggested change: Record when the launcher removed nvidia (for example a state marker file), put it back only when that marker exists, then clear it, and drop the -n guard.

Reproducer (fails at 48bbdbf)

Reproducer: the launcher adds nvidia to lists that never had it, and cannot restore a list that was only nvidia

Reviewed head: 48bbdbf6022e482a1ccde831e517b56e47438c8a

Append either case to the end of test/shell.d/launch-activity-test.sh (it reuses that file's write_conf, launch and shown_gpus helpers and its stubbed omarchy-hw-nvidia-suspended), then run bash test/shell.d/launch-activity-test.sh. Each case was run on its own copy of the file.

Case 1: a list without nvidia, card awake (or no NVIDIA GPU at all)

omarchy-hw-nvidia-suspended also exits 1 when the machine has no NVIDIA display device (the PR's own detector test "a machine with no NVIDIA display device is not reported as suspended"), so the stub returning false covers both an awake card and a machine without one.

write_conf "amd intel"
OMARCHY_TEST_NVIDIA_SUSPENDED=false launch
[[ $(shown_gpus) == "amd intel" ]] || fail "a list without nvidia is left alone while the card is awake" "$(<"$btop_conf")"
pass "a list without nvidia is left alone while the card is awake"

Actual output at 48bbdbf:

ok - a suspended NVIDIA GPU is left out of shown_gpus
ok - an awake NVIDIA GPU is put back into shown_gpus
ok - a list without nvidia is left alone
ok - Activity launches without a btop config
#* Set which GPU vendors to show.
shown_gpus = "nvidia amd intel"

custom_gpu_name0 = ""
not ok - a list without nvidia is left alone while the card is awake

Exit status 1.

Case 2: a list that is only nvidia

write_conf "nvidia"
OMARCHY_TEST_NVIDIA_SUSPENDED=true launch
OMARCHY_TEST_NVIDIA_SUSPENDED=false launch
[[ $(shown_gpus) == "nvidia" ]] || fail "a list of only nvidia is put back once the card is awake" "$(<"$btop_conf")"
pass "a list of only nvidia is put back once the card is awake"

Actual output at 48bbdbf:

ok - a suspended NVIDIA GPU is left out of shown_gpus
ok - an awake NVIDIA GPU is put back into shown_gpus
ok - a list without nvidia is left alone
ok - Activity launches without a btop config
#* Set which GPU vendors to show.
shown_gpus = ""

custom_gpu_name0 = ""
not ok - a list of only nvidia is put back once the card is awake

Exit status 1. The first launch writes shown_gpus = ""; the second skips the file because of the [[ -n $shown ]] guard, so nvidia never comes back.

More findings: symlinked btop.conf is replaced by a regular file

Symlinked btop.conf is replaced by a regular file

sed -i without --follow-symlinks replaces a symlinked ~/.config/btop/btop.conf with a regular file on the first launch while the card sleeps, detaching it from the user's dotfiles.

Suggested change: Use sed -i --follow-symlinks, as omarchy-theme-set-vscode does.

Reproducer (fails at 48bbdbf)

Reproducer: a symlinked btop.conf is replaced by a regular file

Reviewed head: 48bbdbf6022e482a1ccde831e517b56e47438c8a

Append this case to the end of test/shell.d/launch-activity-test.sh (it reuses that file's tmp_dir, btop_conf, write_conf, launch and shown_gpus helpers), then run bash test/shell.d/launch-activity-test.sh.

write_conf "nvidia amd intel"
mkdir -p "$tmp_dir/dotfiles"
mv "$btop_conf" "$tmp_dir/dotfiles/btop.conf"
ln -s "$tmp_dir/dotfiles/btop.conf" "$btop_conf"
OMARCHY_TEST_NVIDIA_SUSPENDED=true launch
[[ -L $btop_conf ]] || fail "a symlinked btop.conf stays a symlink" "$(ls -l "$btop_conf" | cut -c1)"
[[ $(shown_gpus) == "amd intel" ]] || fail "a symlinked btop.conf is edited through the link" "$(<"$btop_conf")"
pass "a symlinked btop.conf is edited through the link"

Actual output at 48bbdbf:

ok - a suspended NVIDIA GPU is left out of shown_gpus
ok - an awake NVIDIA GPU is put back into shown_gpus
ok - a list without nvidia is left alone
ok - Activity launches without a btop config
-
not ok - a symlinked btop.conf stays a symlink

Exit status 1. The - is the file-type column of ls -l: after the launch, ~/.config/btop/btop.conf is a regular file holding shown_gpus = "amd intel", and the linked file in the dotfiles directory still says shown_gpus = "nvidia amd intel". GNU sed -i without --follow-symlinks writes a new file and renames it over the link. With sed -i --follow-symlinks the same case passes.

Details

Verified:

  • btop 1.4.7 calls Gpu::Nvml::init() at startup whenever shown_gpus contains nvidia, whatever boxes are shown (src/linux/btop_collect.cpp:371-374).
  • The detector reads only cached sysfs fields (vendor, class, power/runtime_status), and returns suspended only when every NVIDIA display-class function is suspended; transitional and unsupported states keep nvidia in the list.
  • The shipped list nvidia amd intel becomes amd intel while the card is suspended and is restored byte for byte once it is awake.
  • Super+Ctrl+T resolves to omarchy-launch-activity and keeps the org.omarchy.btop app id and float rule.
  • Both new test files pass at the head and fail without the scripts.

Rebase and overlap: the PR conflicts with current quattro in default/hypr/bindings/utilities.lua (neighbouring bindings changed; the Activity line itself did not). Open PR #8661 changes the same Activity line to { tui = "btop", focus = "current-workspace" }, so whichever lands second needs to carry the other's behaviour.

Optional notes:

  • The edit persists: after an Activity launch while the card sleeps, a btop started from a terminal omits NVIDIA until Activity is next opened with the card awake.
  • Reverting the binding to { tui = "btop" } survives the tests; a one-line grep -F check like the one in launch-1password-test.sh would cover it.

Review information

Test scope: Source code and sandbox tests (synthetic sysfs and HOME) at 48bbdbf; btop itself and NVIDIA hardware not tested.

AI process: Opus 5.5 Medium coordination and synthesis, Opus 5.5 Xhigh technical review and final fact check, GPT 6 Sol Xhigh search for related issues, Opus 5.5 Medium editorial check.

Opt out: To stop receiving these reviews, reply to this comment saying so.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants